package com.wjbgn.bsolver.gateway.controller;

import cn.hutool.crypto.digest.MD5;
import com.wjbgn.bsolver.gateway.client.dto.UserDTO;
import com.wjbgn.bsolver.gateway.enums.CommonReturnEnum;
import com.wjbgn.bsolver.gateway.util.dto.Result;
import com.wjbgn.bsolver.gateway.util.jwt.JwtUtil;
import com.wjbgn.bsolver.gateway.util.redis.RedisUtil;
import com.wjbgn.bsolver.gateway.util.threadpool.GlobalThreadPool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;

/**
 * 用户注册控制器
 *
 * @author weirx
 * @date 2022/03/11 10:24
 **/
@Slf4j
@RestController
@RequestMapping("/user")
public class RegisterController {

    private final static String USER_REGISTER_PATH = "http://bsolver-user/user/save";


    @Autowired
    private WebClient.Builder webClientBuilder;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 用户注册
     *
     * @param userDTO
     * @return com.wjbgn.bsolver.gateway.util.dto.Result
     * @author weirx
     * @date: 2022/3/11
     */
    @PostMapping("/register")
    public Result register(@RequestBody UserDTO userDTO) {
        // 密码md5加密
        userDTO.setPassword(MD5.create().digestHex(userDTO.getPassword()));
        Mono<Result> monoInfo = webClientBuilder
                .build().post().uri(USER_REGISTER_PATH)
                .body(BodyInserters.fromValue(userDTO)).header(HttpHeaders.CONTENT_TYPE, "application/json")
                .retrieve().bodyToMono(Result.class);

        // 异步调用block方法，否则会报错，因为block的内部方法blockingGet是同步方法。
        CompletableFuture<Result> voidCompletableFuture = CompletableFuture.supplyAsync(()->
                monoInfo.block(Duration.ofMillis(500)), GlobalThreadPool.getExecutor());
        try {
            Result result = voidCompletableFuture.get();
            if (result.getCode() == CommonReturnEnum.SUCCESS.getCode()) {
                // 注册成功，直接生成token，登录成功
                String token = JwtUtil.generateToken(userDTO.getUsername());
                // 将token放入redis
                redisUtil.setObjectExpire(JwtUtil.REDIS_TOKEN_PREFIX + userDTO.getUsername(), token, Duration.ofMinutes(JwtUtil.REDIS_TOKEN_EXPIRE_MINUTE));
                return Result.success("注册成功", new UserDTO(userDTO.getUsername(), token));
            } else {
                return result;
            }
        } catch (Exception e) {
            log.info("注册失败");
        }
        return Result.failed("注册失败");
    }

}
